package com.charging.business.handle;


import com.charging.business.config.MinFeeManager;
import com.charging.business.enums.Issuer;
import com.charging.business.enums.SpecialSituation;
import com.charging.business.enums.Vclass;
import com.charging.business.enums.Vsign;
import com.charging.business.exception.CustomizeException;
import com.charging.business.jin.JinOnLineRequest;
import com.charging.business.qin.Db3FileUtils;
import com.charging.business.utils.BasicUtil;
import com.charging.business.utils.PayUtil;
import com.charging.business.utils.RosterUtils;
import com.charging.business.vo.CustomOnlineResponse;
import com.charging.business.vo.FeeExCalcRequest;
import com.charging.business.vo.FeeExCalcResponse;
import com.charging.business.vo.obj.MiniFeeInfo;
import com.charging.business.vo.obj.OnlineFeeInfo;
import com.charging.business.vo.obj.SplitProvinceMini;
import com.charging.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 出口刷ETC卡计费
 *
 * @author lzj
 */
@Component
public class FeeExEtcHandle {
    private static final Logger logger = LoggerFactory.getLogger(FeeExEtcHandle.class);

    private static boolean beWantMinFee = false;
    //用户卡车种
    public int ucVehicleClass = 0;
    //出口车种
    public int exVehicleClass = 0;
    //特殊车辆标识
    public int exVehicleSign = 255;
    //出口车牌(含颜色)
    public String exVehicleId = "";
    //用户卡车牌(含颜色)
    public String ucVehicleId = "";

    @Autowired
    private MinFeeManager minFeeManager;

    @Autowired
    private Db3FileUtils db3FileUtils;

    @Autowired
    private RosterUtils rosterUtils;

    public FeeExCalcResponse run(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        // 1、分析obu文件信息内容,解析到实体里
        request.parseTagFiles();
        // 2、对入出口时间、车牌、车型、轴数、车种、发行方等先批量处理
        this.init(request);
        // 3、兜底计费
        long s1 = System.currentTimeMillis();
        response = this.getMinFee(request, response);
        long s2 = System.currentTimeMillis();
        logger.info("最小费额算费结束,耗时{}毫秒", s2 - s1);
        // 4、在线特情计费
        response = this.specialFee(request, response);

        return response;
    }

    /**
     * 批量处理基本数据，设置异常特情
     *
     * @param request
     */
    public void init(FeeExCalcRequest request) {
        ucVehicleId = BasicUtil.formatVehicleId(request.card0015Model.getPlateNo(request.card0015Model.plateColor));
        String uc0019VehicleId = BasicUtil.formatVehicleId(request.card0019Model.getPlateNo(request.card0019Model.plateColor));
        exVehicleId = BasicUtil.formatVehicleId(request.getVehicleId());
        //重置特情类型
        BasicUtil.resetSpecialInfo();
        //入出口车型对比
//        if (!request.getEnVehicleType().equals(request.getExVehicleType())) {
//            BasicUtil.setSpecialInfo(SpecialSituation.TYPE51.getValue());
//            logger.warn(SpecialSituation.TYPE51.getDescription());
//        }
        //入出口车牌对比
        if (!BasicUtil.compareVehicleId(exVehicleId, ucVehicleId, true) || !BasicUtil.compareVehicleId(exVehicleId, uc0019VehicleId, true)) {
            BasicUtil.setSpecialInfo(SpecialSituation.TYPE52.getValue());
            logger.warn(SpecialSituation.TYPE52.getDescription());
        } else if (!BasicUtil.compareVehicleId(ucVehicleId, uc0019VehicleId, true)) {
            BasicUtil.setSpecialInfo(SpecialSituation.TYPE41.getValue());
            logger.warn(SpecialSituation.TYPE41.getDescription());
        }
        //入出口轴数对比
//        if (request.getEnAxleCount() != request.getExAxleCount()) {
//            BasicUtil.setSpecialInfo(SpecialSituation.TYPE60.getValue());
//            logger.warn(SpecialSituation.TYPE60.getDescription());
//        }
        //U型车检查
        if (Objects.equals(request.getEnStationHex(), request.getExStationHex())) {
            BasicUtil.setSpecialInfo(SpecialSituation.TYPE111.getValue());
            logger.warn(SpecialSituation.TYPE111.getDescription());
        }
        //入出口车种处理
        ucVehicleClass = Vclass.getEtcVCLASS(request.getExVehicleType(), request.card0015Model.vehicleUserType, -1, ucVehicleId);
        exVehicleClass = Vclass.getEtcVCLASS(request.getExVehicleType(), request.vehicleUserType, -1, exVehicleId);
        List<Integer> values = Arrays.asList(Vclass.MTC_GREEN, Vclass.MTC_COMHV, Vclass.MTC_LARGE);
        if (values.contains(exVehicleClass)) {
            // 出口为绿通、联合收割、大件运输
            if (exVehicleClass == Vclass.MTC_GREEN) {
                exVehicleSign = Vsign.GREEN;
            } else if (exVehicleClass == Vclass.MTC_COMHV) {
                exVehicleSign = Vsign.COMHV;
            } else if (exVehicleClass == Vclass.MTC_LARGE) {
                exVehicleSign = Vsign.ETCLARGE;
            }

            if (BasicUtil.compareVehicleId(exVehicleId, ucVehicleId, false)) {
                exVehicleClass = ucVehicleClass;
            }
        }

        logger.info("卡基本信息：卡内部编号：{}，卡片网络编号：{}，发行方：{}，车牌号：[{}]-[{}]，用户类型：{}，车型：{}，状态标识：{}",
                request.card0015Model.cardNo, request.card0015Model.cardWork, request.card0015Model.issueSign, ucVehicleId,
                uc0019VehicleId, request.card0015Model.vehicleUserType, request.card0019Model.vehicleType, request.card0019Model.vehicleSign);

        logger.info("请求参数信息：入出口站：[{}]-[{}]，入出口时间：[{}]-[{}]，入出口车牌：[{}]-[{}]-[{}]，入出口车型：[{}]-[{}]，入出口轴数：[{}]-[{}]，入出口车种：[{}]-[{}]，用户类型：{}，状态标识：{}，passId：{}", request.getEnStationId(), request.getExStationId(), DateUtils.convertTime(request.getEnTime()), DateUtils.convertTime(request.getExTime()), ucVehicleId, uc0019VehicleId, exVehicleId, request.getEnVehicleType(), request.getExVehicleType(), request.getEnAxleCount(), request.getExAxleCount(), ucVehicleClass, exVehicleClass, request.getVehicleUserType(), request.getVehicleSign(), request.getPassId());
    }

    /**
     * 兜底计费，分省合并
     *
     * @param request
     * @param response
     * @return
     * @throws CustomizeException
     */
    public FeeExCalcResponse getMinFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        // 获取最小费额版本号
        boolean bETC = true;
        try {
            MiniFeeInfo miniFeeInfo = new MiniFeeInfo();
            String minVersion = minFeeManager.getCurrentVersion();
            miniFeeInfo.spcRateVersion = minVersion;
            ArrayList<SplitProvinceMini> minProvinces = new ArrayList<>();
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                //陕西
                try {
                    db3FileUtils.loadDb3File(request.getEnStationId(), request.getExStationId(), request.getExVehicleType());
                    minProvinces = minFeeManager.getMinFee(bETC, request.getEnStationId(), request.getExStationId(), request.getExVehicleType());
                } catch (Exception e) {
                    throw new CustomizeException("获取最小费额失败");
                }
            } else {
                minProvinces = rosterUtils.getMiniFee(request.getEnStationId(), request.getExStationId(), request.getExVehicleType(), request.getExAxleCount(), bETC);
            }
            if (minProvinces.isEmpty()) {
                throw new CustomizeException("获取兜底计费失败：查询不到对应的出口计费信息");
            }
            // 汇总最小费额信息
            for (SplitProvinceMini prov : minProvinces) {
                miniFeeInfo.zMinPayFee += prov.ziMinPayFee;
                miniFeeInfo.zMinFee += prov.ziMinFee;
                miniFeeInfo.calMinFeeFee += prov.calMinFeeFee;
                miniFeeInfo.calMinFeeFee95 += prov.calMinFeeFee95;
                miniFeeInfo.calMinFeeMileage += prov.calMinFeeMileage;
            }
            miniFeeInfo.splitProvince = minProvinces;
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                miniFeeInfo.merge();
            }

            response.setSpcRateVersion(minVersion);
            response.setRateVersion(miniFeeInfo.splitProvince.get(miniFeeInfo.splitProvince.size() - 1).rateVersion);
            response.setMiniFeeInfo(miniFeeInfo);
            response.setExitFeeType(6);

            logger.info("最小费额结果：通行省份个数：{},总应收：{}元,总实收：{}元,95折总实收：{}元,总里程：{}公里,费额费率版本号：{}", miniFeeInfo.splitProvince.size(), PayUtil.convertFee(miniFeeInfo.calMinFeeFee), PayUtil.convertFee(miniFeeInfo.zMinFee), PayUtil.convertFee(miniFeeInfo.calMinFeeFee95), PayUtil.convertMileage(miniFeeInfo.calMinFeeMileage), minVersion);
        } catch (CustomizeException e) {
            throw new CustomizeException(!e.getCustomMessage().isEmpty() ? e.getCustomMessage() : "获取兜底计费异常");
        }
        return response;
    }

    /**
     * 在线特情计费，分省合并
     *
     * @param request
     * @param response
     * @return
     * @throws CustomizeException
     */
    public FeeExCalcResponse specialFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        OnlineFeeInfo onlineFeeInfo = new OnlineFeeInfo();
        CustomOnlineResponse spececReponse = new CustomOnlineResponse();
        long s1 = System.currentTimeMillis();
        if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
            JinOnLineRequest onLineRes = new JinOnLineRequest();
            onLineRes.setMediaId(request.getMediaNo());
            onLineRes.setExStationId(request.getExStationHex() + "|" + request.getExStationId());
            onLineRes.setExTime(request.getExTime());
            onLineRes.setVehicleId(request.getVehicleId());
            onLineRes.setVehicleType(request.getExVehicleType());
            onLineRes.setVehicleClass(request.getVehicleClass());
            if (request.getPayType() != null) {
                onLineRes.setPayType(request.getPayType());
            }
            onLineRes.setPassId(request.getPassId());
            onLineRes.setEnStationId(request.getEnStationHex() + "|" + request.getEnStationId());
            onLineRes.setFeeType(1);
            onLineRes.setAxleCount(request.getExAxleCount());
            onLineRes.setEnTime(request.getEnTime());
            onLineRes.setSecondConfirm(1);
            onLineRes.setIsETC(request.getIsDiscount());
            onLineRes.setMediaType(request.getMediaType());
            onLineRes.setEnTollLaneId(request.getEnTollLaneId());
            onLineRes.setExTollLaneId(request.getExTollLaneId());
            onLineRes.setIsMultiProv(1);
            onLineRes.setVehicleUserType(request.getVehicleUserType());
            onLineRes.setIssuerId(request.getIssuerId());
            onLineRes.setCardId(request.card0015Model.getCardId20());
//            onLineRes.setReqVersion(Long.parseLong(DateUtils.dateTime()));
            onLineRes.setVehicleSign(request.getVehicleSign());
            spececReponse = rosterUtils.getJinExOnlineFee(onLineRes, response);
        }
//        else {
//            QinOnLineRequest onLineRes = new QinOnLineRequest();
//            onLineRes.setRequestId(IdUtils.fastSimpleUUID());
////            onLineRes.setSplitProvince(IdUtils.fastSimpleUUID());
//            onLineRes.setRequestType(11);
//            if (request.obuEf04Model != null && request.obuEf04Model.provCount != 0) {
//                onLineRes.setMultiProvince(request.obuEf04Model.provCount > 1 ? 1 : 0);
//            } else {
//                onLineRes.setMultiProvince(9);
//            }
//            onLineRes.setPassId(request.getPassId());
//            onLineRes.setMediaType(request.getMediaType());
//            onLineRes.setMediaNo(request.getMediaNo());
//            onLineRes.setIssuerId(request.getIssuerId());
////            onLineRes.setIssuerId(request.card0015Model.getIssuerId6());
//            onLineRes.setIsDiscount(request.getIsDiscount());
//            onLineRes.setValidShortFee(request.getValidShortFee() == null || request.getValidShortFee() == 1 ? 1 : 2);
//            onLineRes.setEnLaneId(request.getEnTollLaneId());
//            onLineRes.setEnTime(request.getEnTime());
//            onLineRes.setVehicleId(request.getVehicleId());
//            onLineRes.setExLaneId(request.getExTollLaneId());
//            onLineRes.setExTime(request.getExTime());
//            onLineRes.setVehicleType(request.getExVehicleType());
//            onLineRes.setVehicleUserType(request.getVehicleUserType());
//            onLineRes.setAxleCount(request.getExAxleCount());
//            spececReponse = rosterUtils.getQinExOnlineFee(onLineRes, response);
//        }
        long s2 = System.currentTimeMillis();

        logger.info("在线特情计费算费结束,耗时{}毫秒", s2 - s1);
        if (spececReponse.getOnlineSpececResponse().getCalculateResult() == 1) {
            //设置分省金额明细
            onlineFeeInfo.setSplitProDetail(spececReponse.getOnlineSpececResponse());
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                onlineFeeInfo.merge();
            }
            //设置分省取整金额明细-转现金|其他交易支付方式
            onlineFeeInfo.setRoundSplitProDetail(request.getExStationHex());
            logger.info("在线计费结果：通行省份个数：{}，总应收：{}元，总实收：{}元，总优惠：{}元，总拆分：{}元，总里程：{}公里", onlineFeeInfo.splitProvince.size(), PayUtil.convertFee(onlineFeeInfo.payFee), PayUtil.convertFee(onlineFeeInfo.fee), PayUtil.convertFee(onlineFeeInfo.discountFee), PayUtil.convertFee(onlineFeeInfo.splitAmount), PayUtil.convertMileage(onlineFeeInfo.feeMileage));
        } else {
            beWantMinFee = true;
            logger.info("在线计费失败,走兜底计费");
            return response;
        }

        int spFee = 0;
        int minFee = 0;
        int spMileage = 0;
        int minMileage = 0;
        //在线计费应收金额
        spFee = onlineFeeInfo.getPayFee();
        //最小费额应收金额
        minFee = response.getMiniFeeInfo().calMinFeeFee;
        //在线计费总里程
        spMileage = onlineFeeInfo.getFeeMileage();
        //最小费额里程
        minMileage = response.getMiniFeeInfo().calMinFeeMileage;

        //是否验证最小费额，请求参数里里带入
        if (request.getValidShortFee() == null || request.getValidShortFee() == 1) {
            if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
                //根据山西计费规则。分为客车与6轴以下货车 和6轴以上货车
                if (request.getExVehicleType() < 10 || request.getExAxleCount() <= 6) {
                    if (spFee >= minFee * 0.9f && spFee <= minFee * 1.5f) {
                        // d)在线计费应收金额大于等于最小费额应收下限值且
                        // 在线计费应收金额小于等于最小费额应收上限值时使用在线计费金额计费
                        beWantMinFee = false;
                    } else if (spFee >= minFee * 0.9f && spFee > minFee * 1.5f && spMileage < minMileage * 1.5f) {
                        //e)在线计费应收金额大于等于最小费额应收下限值且
                        //在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程小于最小费额应收里程上限值时使用在线计费金额计费
                        beWantMinFee = false;
                    } else if (spFee >= minFee * 0.9f && spFee > minFee * 1.5f && spMileage > minMileage * 1.5f) {
                        //f)在线计费应收金额大于等于最小费额应收下限值且
                        //在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程大于最小费额应收里程上限值时需要监控授权是否使用在线计费金额，如果监控回控同意则使用
                        logger.info("监控授权...");
//                    beWantMinFee = false;
                    } else {
                        //g)不满足以上条件则转最小费额计费
                        beWantMinFee = true;
                    }
                } else {
                    //6轴以上货车
                    //外省兜底应收金额
                    int otherProMinFee = response.miniFeeInfo.payFeeProvSumOther();
                    //本省兜底应收金额
                    double selfProMinFee = response.miniFeeInfo.payFeeProvSumLocal();
                    // 大于18轴按18轴计算
                    int exAxleCount = request.getExAxleCount() > 18 ? 18 : request.getExAxleCount();
                    double selfProMinFee1 = selfProMinFee * (1 + (exAxleCount - 6) * 0.2f);
                    int provOnlineNum = onlineFeeInfo.getSplitProvince().size();
                    int provMiniNum = response.miniFeeInfo.splitProvince.size();
                    //通行省份个数
                    int provNum = Math.max(provOnlineNum, provMiniNum);
                    double folowFee = (otherProMinFee + selfProMinFee1) - provNum * 50f;
                    beWantMinFee = !(spFee >= folowFee);
                }
            } else {
                //包年车辆：15-绕城包年 16-西阎包年 17-绕城西阎包年
                int vehicleUserType = request.getVehicleUserType();
                int basicAmount = 0;
                double amount = 0;
                double lowAmount;
                double upperAmount = minFee * 5f;
                if (vehicleUserType == 15) {
                    basicAmount = 4371;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 16) {
                    basicAmount = 2825;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 17) {
                    basicAmount = 7196;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else {
                    lowAmount = minFee * 0.9f;
                }

                beWantMinFee = !(spFee >= lowAmount) || !(spFee <= upperAmount);
            }
        }

        if (!beWantMinFee) {
            response.setOnlineFeeInfo(onlineFeeInfo);
        } else {
            response.setExitFeeType(6);
        }
        return response;
    }
}
